home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / fatBitsEdit.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  12KB  |  468 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17. #include <X11/Xaw/Command.h>
  18. #include <X11/Xaw/Toggle.h>
  19. #include <X11/Xaw/Viewport.h>
  20. #include <X11/Xaw/Box.h>
  21. #include <X11/Xaw/Form.h>
  22. #include <X11/Xaw/Scrollbar.h>
  23. #include <X11/Shell.h>
  24. #include <X11/cursorfont.h>
  25. #include <stdio.h>
  26. #ifndef NOSTDHDRS
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #endif
  30. #include "Paint.h"
  31. #include "xpaint.h"
  32. #include "palette.h"
  33. #include "menu.h"
  34. #include "misc.h"
  35. #include "cutCopyPaste.h"
  36.  
  37. #define PADDING    4
  38. #define BW    1
  39.  
  40. typedef struct LocalInfo_s {
  41.     int    curX, curY;
  42.     int    offX, offY, baseX, baseY;
  43.     Widget    cursor;        /* The Box widget */
  44.     Widget    subpaint;    /* the paint widget inside the box */
  45.     Widget    view;        /* the widget in the popup window */
  46.     Widget    paint;        /* The source of this zoom */
  47.     Widget    shell;
  48.  
  49.     int        zoom;        /* paint widget zoom value */
  50.     Position    spX, spY;
  51.     Dimension    spBW;        /* subpaint, x, y and borderwidth */
  52.     struct LocalInfo_s    *next;
  53. } LocalInfo;
  54.  
  55. static LocalInfo    *head = NULL;
  56.  
  57. /*
  58. **  When the popup window is gone, free the storage
  59. */
  60. static void destroyCallback(Widget w, XtPointer larg, void *junk2)
  61. {
  62.     LocalInfo    *l = (LocalInfo *)larg;
  63.     LocalInfo    *c = head, **p = &head;
  64.  
  65.     while (c != NULL && c != l) {
  66.         p = &c->next;
  67.         c = c->next;
  68.     }
  69.  
  70.     if (c != NULL) 
  71.         *p = l->next;
  72.  
  73.     XtFree((XtPointer)l);
  74. }
  75.  
  76. /*
  77. **  Done or WM-Close pressed, destroy widgets
  78. */
  79. static void doneCallback(Widget w, XtPointer larg, void *junk2)
  80. {
  81.     LocalInfo    *l = (LocalInfo *)larg;
  82.  
  83.     /*
  84.     **  Destroy both the cursor and the popup window
  85.     */
  86.         XtDestroyWidget(l->cursor);
  87.         XtDestroyWidget(GetShell(w));
  88. }
  89.  
  90. /*
  91. **  Move the cursor and the view window to the position
  92. **   specified by x,y
  93. */
  94. static void moveCursor(LocalInfo *l, int x, int y, int w, int h)
  95. {
  96.     int    dw, dh;
  97.     int    rx, ry;
  98.  
  99.     if (w == -1 || h == -1) {
  100.         int        z;
  101.         Dimension    wt, ht;
  102.  
  103.         XtVaGetValues(l->view, XtNzoom, &z,
  104.                        XtNwidth, &wt,
  105.                        XtNheight, &ht,
  106.                        NULL),
  107.  
  108.         w = (wt + z - 1) / z;
  109.         h = (ht + z - 1) / z;
  110.     }
  111.  
  112.     XtVaGetValues(l->paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL);
  113.     if (x < 0) x = 0;
  114.     if (y < 0) y = 0;
  115.     if (x + w > dw) x = dw - w;
  116.     if (y + h > dh) y = dh - h;
  117.     if (x < 0 || y < 0) {
  118.         int    z;
  119.  
  120.         XtVaGetValues(l->view, XtNzoom, &z, NULL);
  121.  
  122.         /* XXX zoom bigger than actual */
  123.         return;
  124.     }
  125.  
  126.     rx = x / l->zoom;
  127.     ry = y / l->zoom;
  128.     x  = rx * l->zoom;
  129.     y  = ry * l->zoom;
  130.  
  131.     XtVaSetValues(l->view, XtNzoomX, rx, XtNzoomY, ry, NULL);
  132.     XtVaSetValues(l->cursor, XtNx, x - l->spX - l->spBW - 1, 
  133.                  XtNy, y - l->spY - l->spBW - 1, NULL);
  134.     XtVaSetValues(l->subpaint, XtNzoomX, rx, XtNzoomY, ry, NULL);
  135. }
  136.  
  137. /*
  138. **  Given the popup dimensions, set the "cursor" view to the correct size
  139. */
  140. static void resizeCursor(LocalInfo *l)
  141. {
  142.     Dimension    width, height;
  143.     int        zoom;
  144.     int        pw,ph;
  145.     int        dw,dh;
  146.     int        zx,zy;
  147.  
  148.     XtVaGetValues(l->view, XtNwidth, &width, 
  149.                    XtNheight, &height,
  150.                    XtNzoom, &zoom,
  151.                    NULL);
  152.     XtVaGetValues(l->paint, XtNdrawWidth, &dw, 
  153.                 XtNdrawHeight, &dh, 
  154.                 XtNzoom, &l->zoom, 
  155.                 NULL);
  156.     XtVaGetValues(l->subpaint, XtNzoomX, &zx, 
  157.                    XtNzoomY, &zy, 
  158.                    NULL);
  159.     
  160.     pw = (width + zoom - 1) / zoom;
  161.     ph = (height + zoom - 1) / zoom;
  162.     if ((pw + zx > dw) || (ph + zy > dh)) {
  163.         int    nx,ny;
  164.  
  165.         nx = (pw + zx > dw) ? dw - pw : zx;
  166.         ny = (ph + zy > dh) ? dh - ph : zy;
  167.  
  168.         /*
  169.         **  If the new x or y value off the screen, set it back.
  170.         **    and resize view
  171.         */
  172.         if (nx < 0 || ny < 0) {
  173.             if (nx < 0) {
  174.                 pw += nx;
  175.                 nx  = 0;
  176.             }
  177.             if (ny < 0) {
  178.                 ph += ny;
  179.                 ny  = 0;
  180.             }
  181.             /* XXX -- this really should be SetValues(width,height)
  182.             **        but that doesn't work..?/
  183.             */
  184.             XtResizeWidget(l->view, pw * zoom, ph * zoom, 1);
  185.         }
  186.         moveCursor(l, nx, ny, pw, ph);
  187.     }
  188.  
  189.     pw *= l->zoom;
  190.     ph *= l->zoom;
  191.  
  192.     XtVaSetValues(l->cursor, XtNwidth,  pw + 2 * (PADDING + BW),
  193.                  XtNheight, ph + 2 * (PADDING + BW),
  194.                  NULL);
  195.     XtVaSetValues(l->subpaint, XtNwidth,  pw,
  196.                    XtNheight, ph,
  197.                    NULL);
  198. }
  199.  
  200. /*
  201. **  Button down in the cursor window
  202. */
  203. static void press(Widget w, LocalInfo *l, XButtonEvent *event, Boolean *flg)
  204. {
  205.     Position    x, y;
  206.  
  207.     XtVaGetValues(w, XtNx, &x, XtNy, &y, NULL);
  208.  
  209.     l->offX = event->x;
  210.     l->offY = event->y;
  211.     l->baseX = event->x_root - x;
  212.     l->baseY = event->y_root - y;
  213.     XtVaGetValues(l->paint, XtNzoom, &l->zoom, NULL);
  214. }
  215. static void motion(Widget w, LocalInfo *l, XMotionEvent *event, Boolean *flg)
  216. {
  217.     int        nx, ny;
  218.     int        px, py;
  219.  
  220.     /*
  221.     **  Compress motion events.
  222.     */
  223.     while (XCheckTypedWindowEvent(XtDisplay(w), XtWindow(w), MotionNotify, (XEvent*)event));
  224.  
  225.         nx = event->x_root - l->baseX;
  226.     ny = event->y_root - l->baseY;
  227.  
  228.     px = nx + l->spX + l->spBW + 1;
  229.     py = ny + l->spY + l->spBW + 1;
  230.  
  231.     moveCursor(l, px, py, -1, -1);
  232. }
  233.  
  234. /*
  235. **  If the paint view size changes, update the parent paint window cursor size
  236. */
  237. static void sizeChanged(Widget w, LocalInfo *l, XtPointer junk)
  238. {
  239.     resizeCursor(l);
  240. }
  241.  
  242. /*
  243. **  The parent box widget changed size, resize to fit.
  244. */
  245. static void boxChanged(Widget w, LocalInfo *l, XConfigureEvent *event, Boolean *flg)
  246. {
  247.     Dimension    width, height;
  248.     Dimension    hpad, vpad, bw;
  249.     int        zoom;
  250.  
  251.     XtVaGetValues(l->view, XtNzoom, &zoom, XtNborderWidth, &bw,
  252.                    NULL);
  253.     XtVaGetValues(XtParent(l->view), XtNwidth,  &width,
  254.                      XtNheight, &height,
  255.                          XtNhSpace, &hpad,
  256.                          XtNvSpace, &vpad,
  257.                      NULL);
  258.     width  -= (hpad + bw) * 2 ;
  259.     height -= (vpad + bw) * 2;
  260.  
  261.     /* XXX -- this really should be SetValues(width,height)
  262.     **        but that doesn't work..?/
  263.     */
  264.     XtResizeWidget(l->view, width, height, 1);
  265.  
  266.     resizeCursor(l);
  267. }
  268.  
  269. /*
  270. **  One of the zoom perctange buttons pressed
  271. */
  272. static void buttonCallback(Widget w, XtPointer lArg, void *junk2)
  273. {
  274.     LocalInfo    *l  = (LocalInfo *)lArg;
  275.     char        *lbl;
  276.     int        nz;
  277.     int        cx, cy, zx, zy, z, nw, nh;
  278.     int        x, y;
  279.     Dimension    width, height;
  280.     Boolean        state;
  281.  
  282.     XtVaGetValues(w, XtNstate, &state, XtNlabel, &lbl, NULL);
  283.  
  284.     if (state == False)
  285.         return;
  286.  
  287.     nz = 0;
  288.     sscanf(lbl, "%*d:%d", &nz);
  289.     if (nz == 0)
  290.         return;
  291.  
  292.     XtVaGetValues(l->view, XtNzoomX, &zx, 
  293.                    XtNzoomY, &zy, 
  294.                    XtNzoom, &z,
  295.                    XtNwidth,  &width, 
  296.                    XtNheight, &height, 
  297.                    NULL);
  298.  
  299.     cx = zx + ((width + z - 1) / z) / 2;
  300.     cy = zy + ((height + z - 1) / z) / 2;
  301.     nw = (width + nz - 1) / nz;
  302.     nh = (height + nz - 1) / nz;
  303.  
  304.     XtVaSetValues(l->view, XtNzoom, nz, NULL);
  305.     /*  center on image center */
  306.     x = cx - nw / 2;
  307.     y = cy - nh / 2;
  308.  
  309.     moveCursor(l, x, y, width / nz, height / nz);
  310. }
  311.  
  312. /*
  313. **  Construct the fatbits popup, and cursor
  314. **
  315. */
  316. void FatbitsEdit(Widget paint)
  317. {
  318.     Widget        shell, form, fat;
  319.     Widget        button, box;
  320.     int        i, zoom;
  321.     Colormap    cmap;
  322.     Position    x, y, lx, ly;
  323.     Dimension    width = 48, height = 48;
  324.     LocalInfo    *l;
  325.     static char    *zoomList[] = { 
  326.                 "zoomButton1",
  327.                 "zoomButton2",
  328.                 "zoomButton3",
  329.                 "zoomButton4",
  330.                 "zoomButton5",
  331.             };
  332.     XtTranslations          trans = XtParseTranslationTable("<BtnDown>,<BtnUp>: set() notify()");
  333.     Widget            first = None;
  334.  
  335.     for (l = head; l != NULL && l->paint != paint; l = l->next);
  336.  
  337.     if (l != NULL) {
  338.         XMapRaised(XtDisplay(l->shell), XtWindow(l->shell));
  339.         return;
  340.     }
  341.  
  342.     l = XtNew(LocalInfo);
  343.  
  344.     l->paint = paint;
  345.     l->next  = head;
  346.     head     = l;
  347.  
  348.         XtVaGetValues(paint, XtNcolormap, &cmap, 
  349.                  XtNzoom, &l->zoom, 
  350.                  XtNdownX, &lx, 
  351.                  XtNdownY, &ly, 
  352.                  NULL);
  353.  
  354.         shell = XtVaCreatePopupShell("fatbits", topLevelShellWidgetClass, 
  355.                 GetShell(paint), XtNcolormap, cmap,
  356.                                 NULL);
  357.     l->shell = shell;
  358.     PaletteAddUser(PaletteFind(shell, cmap), shell);
  359.     form  = XtVaCreateManagedWidget("form", formWidgetClass, shell, NULL);
  360.     
  361.     box = XtVaCreateManagedWidget("fatBox", boxWidgetClass, form,
  362.                 XtNbackgroundPixmap, GetBackgroundPixmap(form),
  363.                 NULL);
  364.     XtAddEventHandler(box, StructureNotifyMask, False, (XtEventHandler)boxChanged, (XtPointer)l);
  365.  
  366.  
  367.     fat = XtVaCreateManagedWidget("paint", paintWidgetClass, box,
  368.                 XtNpaint, paint,
  369.                 XtNbottom, XtChainBottom,
  370.                 NULL);
  371.     l->view = fat;
  372.     XtVaGetValues(fat, XtNzoom, &zoom, NULL);
  373.     XtVaSetValues(fat, XtNwidth, width * zoom, 
  374.                XtNheight, height * zoom, 
  375.                NULL);
  376.  
  377.     button = XtVaCreateManagedWidget("done", commandWidgetClass, form,
  378.                 XtNfromVert, box,
  379.                 XtNtop, XtChainBottom,
  380.                 XtNbottom, XtChainBottom,
  381.                 XtNleft, XtChainLeft,
  382.                 XtNright, XtChainLeft,
  383.                 NULL);
  384.  
  385.     XtAddCallback(button, XtNcallback, doneCallback, (XtPointer)l);
  386.  
  387.     ccpAddStdPopup(fat);
  388.  
  389.     first = None;
  390.     for (i = 0; i < XtNumber(zoomList); i++) {
  391.         button = XtVaCreateManagedWidget(zoomList[i], 
  392.                         toggleWidgetClass, form,
  393.                         XtNfromHoriz, button,
  394.                         XtNfromVert, box,
  395.                         XtNtop, XtChainBottom,
  396.                         XtNbottom, XtChainBottom,
  397.                         XtNleft, XtChainRight,
  398.                         XtNright, XtChainRight,
  399.                         XtNradioGroup, first,
  400.                         XtNtranslations, trans,
  401.                         NULL);
  402.         first = button;
  403.         XtAddCallback(button, XtNcallback, buttonCallback, (XtPointer)l);
  404.  
  405.         if (i == XtNumber(zoomList) / 2) {
  406.             XtVaSetValues(button, XtNstate, True, NULL);
  407.         }
  408.     }
  409.  
  410.     XtAddCallback(shell, XtNdestroyCallback, destroyCallback, (XtPointer)l);
  411.     AddDestroyCallback(shell, (void (*)(Widget, void *, XEvent *))doneCallback, (XtPointer)l);
  412.  
  413.         XtPopup(shell, XtGrabNone);
  414.  
  415. #if 0
  416.     XtVaGetValues(fat, XtNwidth, &width, XtNheight, &height, NULL);
  417. #endif
  418.  
  419.     lx -= width / 2;
  420.     ly -= height / 2;
  421.     if (lx < 0) lx = 0;
  422.     if (ly < 0) ly = 0;
  423.  
  424.     x = lx - (PADDING + 2);
  425.     y = ly - (PADDING + 2);
  426.  
  427.     box = XtVaCreateManagedWidget("fatBox", boxWidgetClass, paint,
  428.                 XtNx, x, 
  429.                 XtNy, y,
  430.                 XtNwidth, width + 2 * (PADDING + 1),
  431.                 XtNheight, height + 2 * (PADDING + 1),
  432.                 XtNborderWidth, 1,
  433.                 XtNbackgroundPixmap, GetBackgroundPixmap(paint),
  434.                 NULL);
  435.  
  436.     l->cursor = box;
  437.  
  438.     XtAddEventHandler(box, ButtonPressMask, False, (XtEventHandler)press, (XtPointer)l);
  439.     XtAddEventHandler(box, ButtonMotionMask, False, (XtEventHandler)motion, (XtPointer)l);
  440.  
  441.     l->subpaint = XtVaCreateManagedWidget("fatPaint", paintWidgetClass, box,
  442.                 XtNpaint, paint,
  443.                 XtNzoom, PwZoomParent,
  444.                 XtNx, PADDING,
  445.                 XtNy, PADDING,
  446.                 XtNborderWidth, 1,
  447.                 XtNwidth, width,
  448.                 XtNheight, height,
  449.                 XtVaTypedArg, XtNcursor, XtRString, "fleur", sizeof(Cursor),
  450.                 NULL);
  451.  
  452.     XtAddCallback(l->view, XtNsizeChanged, (XtCallbackProc)sizeChanged, (XtPointer)l);
  453.  
  454.     XtVaGetValues(l->subpaint, XtNx, &l->spX, 
  455.                    XtNy, &l->spY,
  456.                    XtNborderWidth, &l->spBW,
  457.                    NULL);
  458.  
  459.     XtVaSetValues(l->subpaint, XtNzoomX, lx, XtNzoomY, ly, NULL);
  460.     XtVaSetValues(l->view, XtNzoomX, lx, XtNzoomY, ly, NULL);
  461.  
  462.     /*
  463.     **  Set the current operator
  464.     */
  465.     GraphicAdd(fat);
  466.     StateAddParent(shell, paint);
  467. }
  468.